56  绘制条形图

56.1 引言分类数据的可视化

条形图(Bar Plot)是展示分类数据最直观的工具。在金融分析中,条形图帮助我们: - 比较数值:不同类别间的量值对比 - 排名展示:Top N股票、行业排名 - 时间序列对比:同一指标不同时期的变化 - 构成分析:各部分占总体的比例

56.2 条形图 vs 直方图

特性 条形图 直方图
数据类型 分类变量 数值变量
X轴 离散类别 连续区间
条形宽度 可调整,有间隔 固定,无间隔
排列顺序 任意(通常按值排序) 固定(按区间边界)
应用场景 比较、排名 分布形态

56.3 基础条形图

平台任务1解答代码

以下代码与教学平台任务要求完全一致:

列表 56.1
# ⚠️ 平台原始代码 - 请原样输入至教学平台(注释除外),平台才会判定答案正确
import pandas as pd  # 导入Pandas数据分析库
import numpy as np  # 导入NumPy数值计算库

date=["2019年4月","2019年5月","2019年6月","2019年7月","2019年8月"]#创建一个日期的列表

name=['标普500指数','富时100指数','恒生指数','上证综指']#创建一个指数名称的列表

# 创建NumPy数组closeprice
closeprice=np.array([[2945.83,7418.22,29699.11,3078.34],[2752.06,7161.71,26901.09,

2898.70],[2941.76,7425.63,28542.62,2978.88],[2980.38,7586.78,27777.75,2932.51],  # 续行:closeprice=np.array(的数据项

[2926.46,7207.18,25724.73,2886.24]]) #创建收盘价的数据框

index_data = pd.DataFrame(data=closeprice,index=date,columns=name) #生成月末收盘价的数据框

index_return = index_data/index_data.shift(1)-1  #生成月度涨跌幅的数据框

index_return = index_return.dropna() #删除缺失值

print(index_return)  # 输出收益率数据

平台任务2解答代码

以下代码与教学平台任务要求完全一致:

列表 56.2
# ⚠️ 平台原始代码 - 请原样输入至教学平台(注释除外),平台才会判定答案正确
import pandas as pd  # 导入Pandas数据分析库
import numpy as np  # 导入NumPy数值计算库
from pylab import mpl  # 导入mpl模块
import matplotlib.pyplot as plt  # 导入Matplotlib绑图库
plt.rcParams['font.sans-serif']=['SimHei']  # 用黑体显示中文
plt.rcParams['axes.unicode_minus']=False   # 正常显示负号

date=["2019年4月","2019年5月","2019年6月","2019年7月","2019年8月"]#创建一个日期的列表
name=['标普500指数','富时100指数','恒生指数','上证综指']#创建一个指数名称的列表
# 创建NumPy数组closeprice
closeprice=np.array([[2945.83,7418.22,29699.11,3078.34],[2752.06,7161.71,26901.09,
2898.70],[2941.76,7425.63,28542.62,2978.88],[2980.38,7586.78,27777.75,2932.51],  # 续行:closeprice=np.array(的数据项
[2926.46,7207.18,25724.73,2886.24]]) #创建收盘价的数据框
index_data = pd.DataFrame(data=closeprice,index=date,columns=name) #生成月末收盘价的数据框
index_return = index_data/index_data.shift(1)-1  #生成月度涨跌幅的数据框
index_return = index_return.dropna() #删除缺失值
plt.figure(figsize=(11,10))  # 创建图形画布
plt.subplot(2,2,1) #第1行、第1列子图
# 绑制柱状图
plt.bar(x=index_return.columns,height=index_return.iloc[0],width=0.5,label=u"2019年5月涨跌幅",facecolor="y")
plt.xticks (fontsize=13)  # 设置X轴刻度标签
plt.yticks(fontsize=13)  # 设置Y轴刻度标签
plt.ylabel(u"涨跌幅",fontsize=13,rotation=90)  # 设置Y轴标签
plt.legend(loc=9,fontsize=13) #图列放置在中上位置
plt.grid(True)  # 显示网格线
plt.subplot(2,2,2,sharex=plt.subplot(2,2,1),sharey=plt.subplot(2,2,1)) #与第一个子图个的x轴和Y轴相同
# 绑制柱状图
plt.bar(x=index_return.columns,height=index_return.iloc[1],width=0.5,label=u"2019年6月涨跌幅",facecolor="c")
plt.xticks (fontsize=13)  # 设置X轴刻度标签
plt.yticks(fontsize=13)  # 设置Y轴刻度标签
plt.legend(loc=8,fontsize=13) #图列放置在中下位置
plt.ylabel(u"涨跌幅",fontsize=13,rotation=90)  # 设置Y轴标签
plt.grid(True)  # 显示网格线
plt.subplot(2,2,3,sharex=plt.subplot(2,2,1),sharey=plt.subplot(2,2,1))  # 选择子图位置
# 绑制柱状图
plt.bar(x=index_return.columns,height=index_return.iloc[2],width=0.5,label=u"2019年7月涨跌幅",facecolor="b")
plt.xticks (fontsize=13)  # 设置X轴刻度标签
plt.yticks(fontsize=13)  # 设置Y轴刻度标签
plt.legend(loc=9,fontsize=13)  # 添加图例
plt.ylabel(u"涨跌幅",fontsize=13,rotation=90)  # 设置Y轴标签
plt.grid(True)  # 显示网格线
plt.subplot(2,2,4,sharex=plt.subplot(2,2,1),sharey=plt.subplot(2,2,1))  # 选择子图位置
# 绑制柱状图
plt.bar(x=index_return.columns,height=index_return.iloc[3],width=0.5,label=u"2019年8月涨跌幅",facecolor="b")
plt.xticks (fontsize=13)  # 设置X轴刻度标签
plt.yticks(fontsize=13)  # 设置Y轴刻度标签
plt.legend(loc=9,fontsize=13)  # 添加图例
plt.ylabel(u"涨跌幅",fontsize=13,rotation=90)  # 设置Y轴标签
plt.grid(True)  # 显示网格线
plt.savefig("1.png")  # 保存图形至文件
列表 56.3
# ⚠️ 平台原始代码 - 请原样输入至教学平台(注释除外),平台才会判定答案正确
import matplotlib.pyplot as plt  # 导入Matplotlib绑图库
import pandas as pd  # 导入Pandas数据分析库
import numpy as np  # 导入NumPy数值计算库
from pylab import mpl  # 导入mpl模块
 
plt.rcParams['font.sans-serif']=['SimHei']   # 用黑体显示中文
plt.rcParams['axes.unicode_minus']=False     # 正常显示负号

date=["2019年4月","2019年5月","2019年6月","2019年7月","2019年8月"]#创建一个日期的列表
name=['标普500指数','富时100指数','恒生指数','上证综指']#创建一个指数名称的列表
# 创建NumPy数组closeprice
closeprice=np.array([[2945.83,7418.22,29699.11,3078.34],[2752.06,7161.71,26901.09,
2898.70],[2941.76,7425.63,28542.62,2978.88],[2980.38,7586.78,27777.75,2932.51],  # 续行:closeprice=np.array(的数据项
[2926.46,7207.18,25724.73,2886.24]]) #创建收盘价的数据框
index_data = pd.DataFrame(data=closeprice,index=date,columns=name) #生成月末收盘价的数据框
index_return = index_data/index_data.shift(1)-1  #生成月度涨跌幅的数据框
index_return = index_return.dropna() #删除缺失值
plt.figure (figsize=(8,5))  # 创建图形画布
plt.barh(y=index_return.columns,width=index_return.iloc[1],height=0.5,label=u'2019年6月涨跌幅')  # 绑制柱状图
plt.barh(y=index_return.columns,width=index_return.iloc[2],height=0.5,label=u'2019年7月涨跌幅')  # 绑制柱状图
plt.xticks(fontsize=13)  # 设置X轴刻度标签
plt.xlabel(u"涨跌幅",fontsize=13)  # 设置X轴标签
plt.yticks (fontsize=13)  # 设置Y轴刻度标签
plt.title(u"比较4个股指在2019年6月和7月的月度涨跌幅",fontsize=13)  # 设置图表标题
plt.legend (loc=0,fontsize=13)  # 添加图例
plt.grid(True)  # 显示网格线
plt.show()  # 显示图形
plt.savefig("2.png")  # 保存图形至文件

关键参数解析:

  1. color:条形颜色,使用专业配色
  2. alpha:透明度,0.8使图表不显沉重
  3. edgecolor:条形边框,白色增强分隔感
  4. 数值标签:在每个条形顶部标注具体值

56.4 水平条形图

列表 56.4
# =============================================================================
# 题目:水平条形图——股票收益率排名
# =============================================================================
# 本任务演示如何绘制水平条形图,特别适合类别名称较长的情况
# 应用场景:股票排名、基金业绩对比

# ==================== 创建股票数据 ====================
stocks = ['贵州茅台', '五粮液', '招商银行', '中国平安', '平安银行',
          '工商银行', '建设银行', '农业银行', '中国银行', '交通银行']
returns = [0.05, 0.03, 0.02, 0.015, 0.018,
           0.012, 0.011, 0.01, 0.009, 0.008]

df_stocks = pd.DataFrame({
    '股票': stocks,
    '收益率': returns
}).sort_values('收益率')  # 按收益率升序排序(从低到高)

# ==================== 绘制水平条形图 ====================
plt.figure(figsize=(10, 8))

# plt.barh()绘制水平条形图(bar horizontal)
# df_stocks['股票']:Y轴数据(类别)
# df_stocks['收益率']:X轴数据(条形长度)
plt.barh(df_stocks['股票'], df_stocks['收益率'],
         # 使用列表推导式根据收益率值选择颜色
         # 收益率 > 3%:红色(突出显示高收益)
         # 收益率 ≤ 3%:青色(普通收益)
         color=['#E3120B' if x > 0.03 else '#008080' for x in df_stocks['收益率']],
         alpha=0.8)

# ==================== 添加数值标签 ====================
# df_stocks.iterrows():遍历DataFrame的每一行
# i:索引(行的位置)
# idx:行索引(原始索引)
# row:行的数据(Series对象)
for i, (idx, row) in enumerate(df_stocks.iterrows()):
    # plt.text()在图上添加文字
    # row['收益率'] + 0.002:X坐标(条形右侧0.002个单位)
    # i:Y坐标(第i个条形的Y位置)
    # f'{row["收益率"]:.1%}':文字内容(百分比格式,保留1位小数)
    # va='center':垂直对齐方式为居中
    plt.text(row['收益率'] + 0.002, i, f'{row["收益率"]:.1%}',
             va='center', fontsize=10)

# ==================== 设置图表装饰 ====================
plt.title('股票收益率排名', fontsize=16, fontweight='bold')
plt.xlabel('收益率', fontsize=12)
plt.ylabel('股票', fontsize=12)
# axis='x':只显示X轴网格线(垂直网格线)
plt.grid(axis='x', alpha=0.3)
plt.tight_layout()
plt.show()

# ==================== 输出统计信息 ====================
print('收益率统计:')
print(f'最高: {df_stocks["收益率"].max():.2%}')
print(f'最低: {df_stocks["收益率"].min():.2%}')
print(f'平均: {df_stocks["收益率"].mean():.2%}')

水平 vs 垂直条形图:

场景 推荐类型 理由
类别名称较长 水平 避免标签重叠
类别数量多(>10) 水平 更易阅读
时间序列 垂直 符合时间从左到右的习惯
数值比较 垂直 长度差异更直观

颜色编码技巧: - 用不同颜色突出重要类别(如收益率>3%用红色) - 保持配色简洁,避免使用过多颜色 - 参考《经济学人》等专业图表的配色

56.5 分组条形图

列表 56.5
# =============================================================================
# 题目:分组条形图——多指标对比
# =============================================================================
# 本任务演示如何绘制分组条形图,在同一类别中对比多个指标
# 应用场景:年度财务指标对比、多维度绩效评估

# ==================== 创建多年度数据 ====================
years = ['2021', '2022', '2023']
revenue = [100, 120, 135]      # 营业收入(亿元)
profit = [15, 18, 22]         # 净利润(亿元)
margin = [15, 15, 16.3]       # 净利率(%)

# ==================== 准备绘图数据 ====================
# np.arange(len(years))生成X轴位置
# [0, 1, 2]:三个年份的位置
x = np.arange(len(years))

# width:每个条形的宽度
# 0.25是一个经验值,太细不好看,太粗易重叠
width = 0.25

# ==================== 创建图形和轴对象 ====================
fig, ax = plt.subplots(figsize=(10, 6))

# ==================== 绘制分组条形 ====================
# 第一组:营业收入
# x - width:向左偏移一个宽度(第一组位置)
# revenue:条形高度
# width:条形宽度
# label='营业收入':图例标签
# color='#2E86AB':深蓝色
bars1 = ax.bar(x - width, revenue, width, label='营业收入',
               color='#2E86AB', alpha=0.8)

# 第二组:净利润
# x:中心位置(不偏移)
bars2 = ax.bar(x, profit, width, label='净利润',
               color='#E3120B', alpha=0.8)

# 第三组:净利率
# x + width:向右偏移一个宽度(第三组位置)
bars3 = ax.bar(x + width, margin, width, label='净利率(%)',
               color='#008080', alpha=0.8)

# ==================== 添加数值标签 ====================
# 循环遍历三个条形组
for bars in [bars1, bars2, bars3]:
    # 遍历组内的每个条形
    for bar in bars:
        # bar.get_height():获取条形的高度
        height = bar.get_height()

        # bar.get_x() + bar.get_width()/2.:计算条形中心X坐标
        # height:Y坐标(条形顶部)
        # f'{height:.1f}':文字内容(保留1位小数)
        ax.text(bar.get_x() + bar.get_width()/2., height,
                f'{height:.1f}', ha='center', va='bottom', fontsize=9)

# ==================== 设置图表装饰 ====================
ax.set_xlabel('年份', fontsize=12)
ax.set_ylabel('金额(亿元)', fontsize=12)
ax.set_title('财务指标年度对比', fontsize=16, fontweight='bold')

# ax.set_xticks()设置X轴刻度位置
ax.set_xticks(x)

# ax.set_xticklabels()设置X轴刻度标签
ax.set_xticklabels(years)
ax.legend(fontsize=11)
ax.grid(axis='y', alpha=0.3)
plt.tight_layout()
plt.show()

# ==================== 计算增长率 ====================
# 2021-2023营业收入增长率
revenue_growth = (revenue[2] - revenue[0]) / revenue[0] * 100
# 2021-2023净利润增长率
profit_growth = (profit[2] - profit[0]) / profit[0] * 100
print(f'2021-2023营业收入增长率: {revenue_growth:.1f}%')
print(f'2021-2023净利润增长率: {profit_growth:.1f}%')

分组条形图的设计要点:

  1. 条形宽度:通常0.2-0.3,太细不好看,太粗易重叠
  2. 间距:组间间距≥组内间距
  3. 颜色:同一组用同一色系,不同组用对比色
  4. 图例:清晰标注每个系列

数学原理: 设 \(n\) 个年份, \(m\) 个指标,第 \(i\) 年第 \(j\) 个指标的条形位置: \[ x_{ij} = i + (j - \frac{m+1}{2}) \times w \] 其中 \(w\) 是条形宽度。

56.6 堆叠条形图

列表 56.6
# =============================================================================
# 题目:堆叠条形图——收入构成分析
# =============================================================================
# 本任务演示如何绘制堆叠条形图,展示整体及各部分的构成
# 应用场景:收入构成、成本结构、投资组合配置

# ==================== 创建收入构成数据 ====================
years = ['2021', '2022', '2023']
primary_business = [80, 90, 100]      # 主营业务收入(亿元)
other_business = [15, 20, 25]         # 其他业务收入(亿元)
investment_income = [5, 10, 10]       # 投资收益(亿元)

# ==================== 创建图形和轴对象 ====================
fig, ax = plt.subplots(figsize=(10, 6))

# ==================== 绘制堆叠条形图 ====================
# 第一层:主营业务收入(底层)
ax.bar(years, primary_business, label='主营业务收入',
       color='#2E86AB', alpha=0.8)

# 第二层:其他业务收入(堆叠在第一层之上)
# bottom=primary_business:起始高度为第一层的顶部
ax.bar(years, other_business, bottom=primary_business,
       label='其他业务收入', color='#008080', alpha=0.8)

# 第三层:投资收益(堆叠在第二层之上)
# bottom=[p+o for p, o in zip(primary_business, other_business)]:
#   起始高度为前两层之和(使用列表推导式计算)
ax.bar(years, investment_income,
       bottom=[p+o for p, o in zip(primary_business, other_business)],
       label='投资收益', color='#F0A700', alpha=0.8)

# ==================== 添加总数值标签 ====================
for i, year in enumerate(years):
    # total:该年份的总收入(三层之和)
    total = primary_business[i] + other_business[i] + investment_income[i]

    # ax.text()在图上添加文字
    # i:X坐标(第i个条形)
    # total + 5:Y坐标(条形顶部上方5个单位)
    # f'{total}':文字内容(总收入值)
    # ha='center':水平居中
    # va='bottom':垂直底部对齐
    # fontsize=11, fontweight='bold':字号11,加粗
    ax.text(i, total + 5, f'{total}', ha='center', va='bottom',
            fontsize=11, fontweight='bold')

# ==================== 设置图表装饰 ====================
ax.set_xlabel('年份', fontsize=12)
ax.set_ylabel('收入(亿元)', fontsize=12)
ax.set_title('收入构成变化', fontsize=16, fontweight='bold')
# loc='upper left':图例位置在左上角
ax.legend(fontsize=11, loc='upper left')
ax.grid(axis='y', alpha=0.3)
plt.tight_layout()
plt.show()

# ==================== 计算占比变化 ====================
print('各业务占比变化:')
for i, year in enumerate(years):
    total = primary_business[i] + other_business[i] + investment_income[i]
    # 计算各业务占比
    primary_pct = primary_business[i] / total * 100
    other_pct = other_business[i] / total * 100
    invest_pct = investment_income[i] / total * 100
    print(f'{year}: 主营{primary_pct:.1f}%, 其他{other_pct:.1f}%, 投资{invest_pct:.1f}%')

堆叠条形图的应用场景:

  1. 构成分析:展示整体及各部分
  2. 变化追踪:观察构成的时间变化
  3. 对比分析:不同类别的构成差异

注意事项: - 不适合比较各部分的大小(基线不统一) - 适合展示各部分占总体的比例 - 考虑用百分比堆叠图使比例更清晰

56.7 百分比堆叠条形图

列表 56.7
# =============================================================================
# 题目:百分比堆叠条形图——投资组合配置
# =============================================================================
# 本任务演示如何绘制百分比堆叠条形图,展示各部分的相对比例
# 应用场景:资产配置变化、市场份额分析

# ==================== 创建资产配置数据 ====================
years = ['2020', '2021', '2022', '2023', '2024']
stocks = [60, 65, 55, 50, 45]      # 股票配置(万元)
bonds = [30, 25, 30, 35, 40]       # 债券配置(万元)
cash = [10, 10, 15, 15, 15]        # 现金配置(万元)

# ==================== 转换为百分比 ====================
# np.array()将列表转换为NumPy数组(便于向量运算)
total = np.array(stocks) + np.array(bonds) + np.array(cash)

# 计算百分比
stocks_pct = np.array(stocks) / total * 100
bonds_pct = np.array(bonds) / total * 100
cash_pct = np.array(cash) / total * 100

# ==================== 创建图形和轴对象 ====================
fig, ax = plt.subplots(figsize=(10, 6))

# ==================== 绘制百分比堆叠条形图 ====================
# 第一层:股票(底层)
ax.bar(years, stocks_pct, label='股票',
       color='#E3120B', alpha=0.8)

# 第二层:债券(堆叠在股票之上)
# bottom=stocks_pct:起始高度为股票百分比
ax.bar(years, bonds_pct, bottom=stocks_pct,
       label='债券', color='#008080', alpha=0.8)

# 第三层:现金(堆叠在债券之上)
# bottom=stocks_pct + bonds_pct:起始高度为股票+债券百分比
ax.bar(years, cash_pct, bottom=stocks_pct + bonds_pct,
       label='现金', color='#F0A700', alpha=0.8)

# ==================== 添加百分比标签 ====================
for i, year in enumerate(years):
    # 股票标签(在第一层中间)
    ax.text(i, stocks_pct[i]/2, f'{stocks_pct[i]:.0f}%',
            ha='center', va='center', color='white', fontweight='bold')

    # 债券标签(在第二层中间)
    ax.text(i, stocks_pct[i] + bonds_pct[i]/2, f'{bonds_pct[i]:.0f}%',
            ha='center', va='center', color='white', fontweight='bold')

    # 现金标签(在第三层中间)
    ax.text(i, stocks_pct[i] + bonds_pct[i] + cash_pct[i]/2, f'{cash_pct[i]:.0f}%',
            ha='center', va='center', color='white', fontweight='bold')

# ==================== 设置图表装饰 ====================
ax.set_xlabel('年份', fontsize=12)
ax.set_ylabel('配置比例(%)', fontsize=12)
ax.set_title('投资组合配置变化', fontsize=16, fontweight='bold')
# ax.set_ylim(0, 100):设置Y轴范围为0-100%
ax.set_ylim(0, 100)
# loc='upper right':图例位置在右上角
# bbox_to_anchor=(1.15, 1):将图例放置在图表外侧(右侧)
ax.legend(fontsize=11, loc='upper right', bbox_to_anchor=(1.15, 1))
ax.grid(axis='y', alpha=0.3)
plt.tight_layout()
plt.show()

# ==================== 分析配置策略变化 ====================
print('配置策略变化:')
print(f'股票配置: 从{stocks_pct[0]:.0f}%降至{stocks_pct[-1]:.0f}%')
print(f'债券配置: 从{bonds_pct[0]:.0f}%升至{bonds_pct[-1]:.0f}%')
print('策略: 逐步从激进型转向稳健型')

56.8 金融应用杜邦分析

列表 56.8
# =============================================================================
# 题目:杜邦分析——ROE分解
# =============================================================================
# 本任务演示如何使用条形图展示杜邦分析的三个因子
# 应用场景:财务分析、ROE分解、公司对比

# ==================== 杜邦分析数据 ====================
# 杜邦分析公式:ROE = 销售净利率 × 总资产周转率 × 权益乘数
companies = ['公司A', '公司B', '公司C', '公司D', '公司E']

# ROE分解的三个因子
net_margin = [15, 10, 8, 20, 12]           # 销售净利率(%)
asset_turnover = [1.2, 1.5, 0.8, 1.0, 1.3]  # 总资产周转率
equity_multiplier = [2.0, 1.8, 2.5, 1.5, 2.2] # 权益乘数

# 计算ROE(净资产收益率)
# ROE = 销售净利率 × 总资产周转率 × 权益乘数 / 100(转换为百分比)
# 使用列表推导式计算每个公司的ROE
roe = [nm * at * em / 100 for nm, at, em in zip(net_margin, asset_turnover, equity_multiplier)]

# ==================== 创建双子图布局 ====================
fig, axes = plt.subplots(1, 2, figsize=(15, 6))

# ==================== 左图:ROE对比 ====================
# axes[0].bar()在第一个子图绘制ROE
axes[0].bar(companies, roe, color='#2E86AB', alpha=0.8)
axes[0].set_title('ROE对比', fontsize=14, fontweight='bold')
axes[0].set_ylabel('ROE (%)', fontsize=12)
# axes[0].set_ylim(0, max(roe) * 1.2):设置Y轴范围为0到最大值的1.2倍
axes[0].set_ylim(0, max(roe) * 1.2)
axes[0].grid(axis='y', alpha=0.3)

# 添加ROE数值标签
for i, v in enumerate(roe):
    axes[0].text(i, v + 1, f'{v:.1f}%', ha='center', va='bottom')

# ==================== 右图:杜邦三因子 ====================
# 准备X轴位置
x = np.arange(len(companies))
# 条形宽度
width = 0.25

# 绘制三个因子的分组条形图
# 第一组:销售净利率
axes[1].bar(x - width, net_margin, width, label='销售净利率(%)',
           color='#E3120B', alpha=0.8)

# 第二组:总资产周转率(×10,使量级与其他因子相当)
axes[1].bar(x, [at * 10 for at in asset_turnover], width,
           label='总资产周转率(x10)', color='#008080', alpha=0.8)

# 第三组:权益乘数(×5,使量级与其他因子相当)
axes[1].bar(x + width, [em * 5 for em in equity_multiplier], width,
           label='权益乘数(x5)', color='#F0A700', alpha=0.8)

axes[1].set_title('杜邦三因子', fontsize=14, fontweight='bold')
axes[1].set_xticks(x)
axes[1].set_xticklabels(companies)
axes[1].legend(fontsize=10)
axes[1].grid(axis='y', alpha=0.3)

plt.tight_layout()
plt.show()

# ==================== 输出杜邦分析表格 ====================
print('杜邦分析:')
# f'{string:^width}':格式化输出,居中对齐
print(f'{"公司":^8s} {"ROE":^8s} {"净利率":^10s} {"周转率":^10s} {"权益乘数":^10s}')
print('-' * 50)
for i, company in enumerate(companies):
    print(f'{company:^8s} {roe[i]:^8.1f} {net_margin[i]:^10.1f} {asset_turnover[i]:^10.2f} {equity_multiplier[i]:^10.2f}')

杜邦分析的金融理论:

\[ \text{ROE} = \frac{\text{净利润}}{\text{股东权益}} = \frac{\text{净利润}}{\text{销售收入}} \times \frac{\text{销售收入}}{\text{总资产}} \times \frac{\text{总资产}}{\text{股东权益}} \]

三因子含义: 1. 销售净利率:盈利能力,每1元销售带来的净利润 2. 总资产周转率:效率,每1元资产创造的销售收入 3. 权益乘数:杠杆,资产与权益的比率

分析要点: - 高ROE可能来自高利润率(如白酒) - 或高周转率(如零售) - 或高杠杆(如银行、地产) - 需结合行业特点综合分析